package org.kim.utils;

import org.kim.core.StorageCache;
import org.kim.pojo.Account;
import org.kim.pojo.Book;
import org.kim.pojo.Borrow;

import java.io.*;
import java.util.Map;
import java.util.stream.Stream;

public class FileUtils {

    private static String filePath = "";

    public static final String STORAGE_PATH = System.getProperty("user.dir") + File.separator + "storage" + File.separator;

    private static final String[] folders = {"Account", "Book", "Borrow"};

    public static void readFile() throws IOException {
        FileReader reader = new FileReader(filePath);
        char[] buffer = new char[1024];

        int length = 0;
        while ((length = reader.read(buffer)) != -1) {

        }

        reader.close();

    }

    public static void writeFile(String record) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileWriter writer = new FileWriter(file, true);
        writer.write(record + "\n");
        writer.close();
    }

    public static void createStorageDict() {
        Stream.of(folders).forEach(
                fo -> {
                    File folder = new File(STORAGE_PATH + fo);
                    if (!folder.exists()) {
                        folder.mkdirs();
                    }
                }
        );
    }

    public static void loadDataFromStorage() throws ClassNotFoundException {
        Stream.of(folders).forEach(
                fo -> {
                    File folder = new File(STORAGE_PATH + fo);
                    Class clazz = null;
                    try {
                        clazz = Class.forName("org.kim.pojo." + fo);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                    if (folder.exists() && folder.isDirectory()) {
                        File[] files = folder.listFiles();
                        for (File file : files) {
                            try {
                                Object obj = clazz.newInstance();
                                obj = deserializeObject(obj, file);
                                storageToCache(obj);
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            } catch (InstantiationException e) {
                                e.printStackTrace();
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }

                    }
                }
        );
    }

    private static void storageToCache(Object obj) {
        if (obj instanceof Account) {
            Account account=(Account)obj;
            StorageCache.accountCache.put(account.getAccountId(), account);
        }
        if (obj instanceof Book) {
            Book book=(Book)obj;
            StorageCache.bookCache.put(book.getName()+"_"+book.getAuthor(), book);
        }
        if (obj instanceof Borrow) {
            Borrow borrow=(Borrow)obj;
            StorageCache.borrowCache.put(borrow.getAccountId()+"_"+borrow.getBookId(), borrow);
        }
    }

    public static void main(String[] args) throws ClassNotFoundException {
        FileUtils.loadDataFromStorage();
    }

    public static void serializeObject(Object obj, String fileName) throws Exception {
        String className = obj.getClass().getSimpleName();
        File file = new File(STORAGE_PATH + File.separator + className + File.separator + fileName);
        FileOutputStream fileOut = new FileOutputStream(file);
        ObjectOutputStream out = new ObjectOutputStream(fileOut);
        out.writeObject(obj);
        out.close();
        fileOut.close();
    }

    public static Object deserializeObject(Object obj, File file) throws Exception {
        FileInputStream fis = new FileInputStream(file);
        ObjectInputStream ios = new ObjectInputStream(fis);
        obj = ios.readObject();
        ios.close();
        fis.close();
        return obj;
    }


    public static void serializeMap(Map<String, Object> map, String fileName) {
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName))) {
            out.writeObject(map);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Map<String, Object> deserializeMap(String fileName) {
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName))) {
            Map<String, Object> map = (Map<String, Object>) in.readObject();
            return map;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

